#!/usr/bin/python
#  Created by Meredith Chang and 13Bit Labs
#  meredith@13bit.com
#  CongressCal is released under GPLv3
#  Copyright 2009 Meredith Chang, 13Bit Labs
#  CongressCal is distributed under the terms of the GNU General Public License 
#  Uses  OpenCongressApi and SunlightLabsApi, Metavid and gData google Api

__author__ = 'meredith@13bit.com (Meredith Chang)'

try:
  from xml.etree import ElementTree
except ImportError:
  from elementtree import ElementTree
import gdata.calendar.service
import gdata.service
import atom.service
import gdata.calendar
import atom
import getopt
import sys
import string
import time
import datetime
import urllib
from elementtree import *

class RepBuilder: 
	
	def __init__(self): 
		self.data = {}
		self.url="http://services.sunlightlabs.com/api/legislators.getList.xml?apikey=9c10cb5b67890452a14a9d5e58ec091b"

	def MakeRepHash(self):	
		root = ElementTree.parse(urllib.urlopen(self.url)).getroot()
		parselist =["district",
			    "firstname",
			    "middlename",
			    "lastname",
		            "twitter_id",
		            "youtube_url",
		            "email",
		            "website"]
		nodes = root.getchildren()[0].getchildren()
                # not working nodes =root.findall("response/legislators/legislator")

		for n in nodes: 
			nlist = [n.findtext(p) for p in parselist ]
			self.data[n.findtext('bioguide_id')] = ' '.join(nlist)
		return self.data



class Rep:
	
	def __init__(self,name,id): 
		self.data = {}
		self.photo = ""
		self.currentbills = []
		self.name  = name
		self.bioguideid = id
		self.path = "/data/"
		self.url = "http://services.sunlightlabs.com/api/legislators.getList.xml?apikey=9c10cb5b67890452a14a9d5e58ec091b"
	



        def FindByZip(self,zip): 
		pass

	def FindByLatLoc(self,lat,loc): 
		pass

        def FindByAddress(self,address): 
		pass
	
	def _ParseRep(self,root): 
		parsehash = ["firstname","lastname","party","state","state","gender","phone","email","votesmart_id","fec_id","govtrack_id","crp_id","eventful_id","congresspedia_url","twitter_id","youtube_url"]
		for node in root: 
			bill = Bill()
			[bill.Add(element,self._Data(node,element)) for element in parsehash['root']]

			for k,v in parsehash.items():
				if k <> "root" : 
					for n in node.findall(k) :
					     	bill.AddList(k,dict([(el,self._Data(n,el)) for el in v]))
					
	 		billdata.append(node)		
		pass					

	def CacheRep(self) : 
		self.url = self.url + "&bioguide_id="+self.bioguide
		root = self._ParseRep(ElementTree.parse(urllib.urlopen(self.url)).getroot())
		tree = ElementTree.ElementTree(root)
		tree.write(self.path+self.bioguideid+"_cache.xml")
			




	def UserPref(self):
		return '<UserPref name="address" display_name="Address/Zip" required="False" />'


	def UserPrefJS(self): 
		js = "<script type='text/javascript'>	"
		js = js + "var prefs = new gadgets.Prefs();"
		js = js + "function loadBio(){"
		js = js + "}"
		js = js + "</script>"

	def GenerateGadget(self): 
		root = ElementTree.Element("xml")
		module = ElementTree.SubElement(root,"Module")
		pref = ElementTree.SubElement(root,"ModulePrefs")
		pref.set("title",self.name)
		content = ElementTree.SubElement(module,"Content")
		content.set("type","html")
		content.text = "<![CDATA[%s]]>"
		tree = ElementTree.ElementTree(root)
		tree.write(self.path+self.bioguideid+".xml")


class Bill: 
	def __init__(self):
		self.data = {}

	def _ConvertDate(self,datestr):
		try:
			return datetime.datetime.fromtimestamp(float(datestr)).strftime("%Y-%m-%d") # %H:%M:%S")
			
		except:
			return datestr
	def Test():
		pass
	def _ParseValue(self,value) : 
		if (value is None) or (len(value) <> 10): 		
			return value
		else :
			return self._ConvertDate(value)
			
	def Add(self,name,value): 
		self.data[name] = self._ParseValue(value)

	def AddList(self,name,value): 
	        for k,v in value.items() :
			value[k]= self._ParseValue(v)	
		if name in self.data :
			self.data[name].append(value)
		else :
			self.data[name] = [value]


	def GetStatus(self): 
		values = ["%s %s" % (a['text'],a['date'],) for a in self.data['most-recent-actions/most-recent-action'] if len(a['text']) > 2 ]
		return "Status: " +self.data['status'] + " <br>" + '<br>,'.join(values)

	def GetUrl(self) :
		pass

	def CalendarFmt(self): 
		cosponsor=[]
		if 'co-sponsors/co-sponsor' in self.data: 
			cosponsor = self.data['co-sponsors/co-sponsor']
		return (self.data['title-full-common'],self.GetStatus(),self.data['bill-type'],self.data['introduced'],self.data['topresident-date'],self.data['sponsor'],cosponsor,) 



	def Print(self): 
		print self.data
class BillStore:

	def __init__(self,loop =True): 
		self.key = "d0138aec323e492d171c831ddfeb393de59d4861"
		self.billdeets = "http://www.opencongress.org/bill/111-%s%s/text"
		self.bills = []
		self.morepages = True
		self.loop = loop
		self.page =1 
      
	def MorePages(self): 
		return self.morepages  

        def Bills(self) : 
		return  self.bills	

	def _Data(self,node,val): 
		try:
	 		return node.findtext(val)
		except: 
			return node.get('text')
	
	def _ParseBills(self,root) : 
	 	parsehash = {'root':["bill-type","introduced","last-speech","last-vote-date","last-vote-roll","last-vote-where","lastaction","sponsor-id","topresident-date","title-full-common","status"],"most-recent-actions/most-recent-action":["date","text"],"sponsor":["bioguideid"],"co-sponsors/co-sponsor":["bioguideid"]}
		billdata = []
		for node in root: 
			bill = Bill()
			[bill.Add(element,self._Data(node,element)) for element in parsehash['root']]

			for k,v in parsehash.items():
				if k <> "root" : 
					for n in node.findall(k) :
					     	bill.AddList(k,dict([(el,self._Data(n,el)) for el in v]))
					
	 		billdata.append(bill)		
		return billdata
				
	

	def LoadBills(self,congress,keep=False) :
		if (not keep) : self.bills = []

		if (self.morepages) : 
	        	self.url = ("http://www.opencongress.org/api/bills?congress=%s&%skey=%s&page=%d") % (congress,"", self.key,self.page) 
			download = self._ParseBills(ElementTree.parse(urllib.urlopen(self.url)).getroot())
			if len(download) == 0 : 
				self.morepages = False
			else:
				self.bills += download
				self.page += 1
		if (not self.loop) : self.morepages = False #remove this

class CongressCal:

	def __init__(self) : 
		self.email = "congresscal@gmail.com"
		self.pwd = "congresscal13"
		self.source = "congresscall"
        	self.events = []	
  		self.cal = gdata.calendar.service.CalendarService()
    		self.cal.email = self.email
    		self.cal.password = self.pwd
    		self.cal.source = self.source
		self.cal.ProgrammaticLogin()
	

	def GetAllBills(self) : 
	   self.events = [feed.entry for feed in  self.cal.GetCalendarEventFeed()]



	def AddCal(self,cal):
		pass

        def UpdateBillStatus(self):	
		pass

	def CreateCalendar(self): 
		pass

	def DeleteAllEvents(self): 
  	 	feed = self.cal.GetCalendarEventFeed()
		for i, event in enumerate(feed.entry):
  			self.cal.DeleteEvent(event.GetEditLink().href)

	def UpdateBill(self, title='New Bill', content='New', where='House',start_time=None, end_time=None, recurrence_data=None):
		try:
			query = gdata.calendar.service(CalendarEventQuery('default','private','full',title)	)
			feed = self.cal.CalendarQuery(query)
  			e = [i for i, an_event in enumerate(feed.entry)]
		except:
	    		event = gdata.calendar.CalendarEventEntry()

	def DeleteBill(self,event): 
		self.cal.DeleteEvent(event.GetEditLink().href)
	
	def FindBillByTitle(self, title='New Bill', content='New', where='House',start_time=None, end_time=None, recurrence_data=None):
		feed = self.cal.GetCalendarEventFeed()
		dellist = []
		retlist =[]
		for i,ev in enumerate(feed.entry) :
			print  (ev.when[0].start_time,ev.when[0].end_time) 
			print (start_time,end_time) 
			print  (ev.when[0].start_time,ev.when[0].end_time) == (start_time,end_time) 
			if (ev.content.text,ev.when[0].start_time,ev.when[0].end_time) != (content,start_time,end_time) :
				print "delete %s" % ev.title.text
				#not matching where yet
				#print ev.where[0].value_string
				print "delete"
				dellist.append(ev.GetEditLink().href)
			else:
			    	retlist.append(ev.title.text)

		for l in dellist : 
			self.cal.DeleteEvent(l) 
		return retlist
		
	def AddBill(self, title='New Bill', content='New', where='House',start_time=None, end_time=None, recurrence_data=None):
	    if len(self.FindBillByTitle(title,content,where,start_time,end_time)) >0 : return 
	
    	    event = gdata.calendar.CalendarEventEntry()
    	    event.title = atom.Title(text=title)
            event.content = atom.Content(text=content)
            event.where.append(gdata.calendar.Where(value_string=where))
            event.content = atom.Content(text=content)
	
    	    if recurrence_data is not None:
                  event.recurrence = gdata.calendar.Recurrence(text=recurrence_data)
            else:
            	if start_time is None:
        		start_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime())
        		end_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z',time.gmtime(time.time() + 3600))
		#print start_time
		#print end_time
		#print "-----"
      	        event.when.append(gdata.calendar.When(start_time=start_time,
          end_time=end_time))

	    event.batch_id = gdata.BatchId(text=title)
    	    #new_event = self.cal.InsertEvent(event,'/calendar/feeds/default/private/full')
            return event
	
        def Batch(self,events):
		feeds = self.cal.GetCalendarEventFeed()
		try:
			for i,event in feeds:
				request_feed.AddDelete(entry=event)
		except:
			pass

		request_feed = gdata.calendar.CalendarEventFeed()
		try :
		   for e in events:
			request_feed.AddInsert(entry=e)
 		   response_feed = self.cal.ExecuteBatch(request_feed, gdata.calendar.service.DEFAULT_BATCH_URL)
		except: 
		    pass




	def Test(self)  : 
		evt = self.AddBill()
	

def main() : 
	#ugly but effective
	cal = CongressCal()
	#cal.DeleteAllEvents() #because update does not work yet
	OCLookup = {"h":"House","s":"Senator", "hj":"House Joint Resolution", "sj":"Senate Joint Resolution","hc":"House Concurrent Resolution","sc":"Senate Concurrent Resolution", "hr":"House Resolution","sr":"Senate Resolution"} 	
	billstore = BillStore()
	while (billstore.MorePages()):
		billstore.LoadBills(111)
		bills = billstore.Bills()
 		reps = RepBuilder()
		biohash = reps.MakeRepHash()
		events = []
		print len(bills)
		for b in bills: 
			
			stuff = b.CalendarFmt()
			title,content,where,start,end,sponsor,sponsors = stuff
			#print start
			#print end
			#print "--"
			where = OCLookup[where]
			content = "Sponsor:<br>%s<br>%s<br>" % ("<br>".join([biohash[s['bioguideid']] for s in sponsors if s['bioguideid'] in biohash]),content,)
			events.append(cal.AddBill(title,content,where,start,end,None))
	
	
		cal.Batch(events)	
	

if __name__ == '__main__':
	main()
